package com.globallogic.training.vaskulg.binarytree;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

public class BinaryTreeTester {
	private BinaryTree<String> testTree;

	@Before
	public void setUp() throws Exception {
		testTree = new BinaryTree<String>("Value of Top Node");
	}

	@Test
	public void shouldCreateObjectWhenCorrectConstructor() {	
		assertTrue(testTree instanceof BinaryTree);
	}
	
	@Test
	public void shouldReturnRootNodeWhenOnlyConstructorIsCalled() {
		assertTrue(testTree.getValue() instanceof String);
	}
	
	@Test
	public void shouldSupportOtherTypeOfNode() {	
		// When
		BinaryTree<Float> floatTree = new BinaryTree<Float>(new Float(3.12));
		
		assertTrue(floatTree.getValue() instanceof Float);
	}
	
	@Test
	public void shouldReturnSameNodeWhenIsCalledTwoTimes() {
		// When
		String firstValue = testTree.getValue();
		String secondValue = testTree.getValue();
		
		// Then
		assertEquals(firstValue, secondValue);
	}
	
	@Test
	public void shouldAddLeftNode() {
		// When
		testTree.addLeftNode("Left Node value");
		testTree.moveLeft();
		
		// Then
		assertEquals("Left Node value", testTree.getValue());

	}
	
	@Test
	public void shouldAddLeftNodeTwice() {
		// When
		testTree.addLeftNode("Left Node value 1");
		testTree.moveLeft();
		
		testTree.addLeftNode("Left Node value 2");
		testTree.moveLeft();
		
		// Then
		assertEquals("Left Node value 2", testTree.getValue());

	}
	
	@Test
	public void shouldAddRightNode() {
		// When
		testTree.addRightNode("Right Node value");
		testTree.moveRight();
		
		// Then
		assertEquals("Right Node value", testTree.getValue());

	}
	
	@Test
	public void shouldAddRightNodeTwice() {
		// When
		testTree.addRightNode("Right Node value 1");
		testTree.moveRight();
		
		testTree.addRightNode("Right Node value 2");
		testTree.moveRight();
		
		// Then
		assertEquals("Right Node value 2", testTree.getValue());

	}
	
	@Test
	public void shouldAddLeftValueToTree_WhenIsLess() {
		String leftValue = "X - Left Value";
		
		testTree.addValue(leftValue);
		
		assertEquals(leftValue, testTree.moveLeft().getValue());
	}
	
	@Test
	public void shouldAddRightValueToTree_WhenIsGreater() {
		String rightValue = "Right Value";
		
		testTree.addValue(rightValue);
		
		assertEquals(rightValue, testTree.moveRight().getValue());
	}
	
	@Test
	public void shouldAddLeftValueTwiceToTree_WhenBothValuesAreLess() {
		// Given
		String leftValue = "X - Left Value";
		String secondLeftValue = "Z - Left Value";
		
		// When
		testTree.addValue(leftValue);
		testTree.addValue(secondLeftValue);
		
		// Then
		testTree.moveLeft();
		assertEquals(secondLeftValue, testTree.moveLeft().getValue());
	}
	
	@Test
	public void shouldAddRightValueTwiceToTree_WhenBothValuesAreGreater() {
		// Given
		String rightValue = "Right Value";
		String secondRightValue = "A - Right Value";
		
		// When
		testTree.addValue(rightValue);
		testTree.addValue(secondRightValue);
		
		// Then
		testTree.moveRight();
		assertEquals(secondRightValue, testTree.moveRight().getValue());
	}
	
	@Test
	public void shouldMoveToParent() {
		// Given
		testTree.addRightNode("Right Node value 1");
		testTree.moveRight();
		
		// When
		testTree.moveToParent();
		
		assertEquals("Value of Top Node", testTree.getValue());
	}
	
	@Test
	public void shouldIndicateWhenMoveingRightToEmptyNode() {
		assertEquals(null, testTree.moveRight());
	}
	
	@Test
	public void shouldIndicateWhenMoveingLeftToEmptyNode() {
		assertEquals(null, testTree.moveLeft());
	}
	
	@Test
	public void shouldIndicateWhenMoveingToParentForRootNode() {
		assertEquals(null, testTree.moveToParent());
	}

}
